package abnormal_txn

import (
	"context"
	"fmt"
	"git.multiverse.io/eventkit/common/model/mgmt"
	"git.multiverse.io/eventkit/dxc-server/client"
	"git.multiverse.io/eventkit/dxc-server/config"
	"git.multiverse.io/eventkit/dxc-server/models"
	"git.multiverse.io/eventkit/kit/client/mesh"
	"git.multiverse.io/eventkit/kit/codec"
	codec_text "git.multiverse.io/eventkit/kit/codec/text"
	"git.multiverse.io/eventkit/kit/constant"
	"git.multiverse.io/framework/log"
	jsoniter "github.com/json-iterator/go"
	"strings"
	"time"
)

var (
	json = jsoniter.ConfigCompatibleWithStandardLibrary
)

func ReportTransactionToDTSManagement(root *models.RootTransaction, reason string) error {
	log.Infosf("Start report transaction[%++v] to DTS management")

	if !config.Cfg.Management.Enable {
		log.Warns("Report transaction to dxc management has disabled, skip...")
		return nil
	}
	abnormalRequest := &mgmt.ReportAbnormalTxnRequest{}
	abnormalRequest.RootXID = root.RootXid
	abnormalRequest.Stat = root.RootTxnStat
	abnormalRequest.GlobalTxnStartTime = root.RootTxnRegisterTime
	abnormalRequest.GlobalTxnEndTime = time.Now()
	abnormalRequest.Reason = reason
	abnormalRequest.Transactions = make([]mgmt.Transaction, 0)
	for _, branch := range root.Branches {
		/* comm type + "|" + Org + "/" + "WKS" + "/" + "ENV" + "/" + "SU" + "/" + "NodeId" + "/" + "InstanceId" + "|" + confirm topicId + "|" + cancel topicId*/
		participantAddressArray := strings.Split(branch.ParticipantAddress, constant.ParticipantAddressSplitChar)

		/* Org + "/" + "WKS" + "/" + "ENV" + "/" + "SU" + "/" + "NodeId" + "/" + "InstanceId" + "|" + confirm topicId + "|" + cancel topicId*/
		topicAttrArray := strings.Split(participantAddressArray[1], constant.TopicIDSplitChat)
		var org, wks, env, su, nodeId, instanceId string

		if strings.EqualFold(constant.CommMesh, participantAddressArray[0]) {
			org, wks, env, su, nodeId, instanceId = topicAttrArray[0], topicAttrArray[1], topicAttrArray[2], topicAttrArray[3], topicAttrArray[4], topicAttrArray[5]
		}
		transactionInfo := mgmt.Transaction{
			RootXID:      branch.RootXid,
			BranchXID:    branch.BranchXid,
			ParentXID:    branch.ParentXid,
			Stat:         branch.BranchTxnStat,
			ORG:          org,
			SU:           su,
			NodeID:       nodeId,
			InstanceID:   instanceId,
			Params:       branch.ParamData,
			Headers:      branch.Headers,
			Environment:  env,
			Workspace:    wks,
			TxnStartTime: branch.BranchTxnStartTime,
			TxnEndTime:   branch.BranchTxnLastUpdateTime,
		}
		abnormalRequest.Transactions = append(abnormalRequest.Transactions, transactionInfo)
	}

	reqBody, err := json.Marshal(abnormalRequest)
	if nil != err {
		return err
	}
	request := mesh.NewMeshRequest(reqBody)
	request.WithOptions(
		mesh.WithTopicTypeDxc(),
		mesh.WithORG(config.Cfg.Service.Org),
		mesh.WithWorkspace(config.Cfg.Service.Wks),
		mesh.WithEnvironment(config.Cfg.Service.Env),
		mesh.WithSU(config.Cfg.Service.Su),
		mesh.WithEventID(config.Cfg.Management.AbnormalTransactionRecordReportTopicID),
		mesh.WithTimeout(time.Duration(config.Cfg.Management.AbnormalTransactionRecordReportTimeoutMilliseconds)*time.Millisecond),
		mesh.WithCodec(codec.BuildCustomCodec(&codec_text.Encoder{}, &codec_text.Decoder{})),
	)
	meshClient := client.DefaultClient
	var respBody []byte
	if _, err = meshClient.SyncCall(context.Background(), request, &respBody); err != nil {
		return err
	}
	commRes := &models.CommonResponse{}
	if err := json.Unmarshal(respBody, commRes); nil != err {
		return err
	}
	success, _ := commRes.CheckSuccess()
	if !success {
		return fmt.Errorf("report transaction to DTS management failed, error code=[%d], error message=[%s]", commRes.ErrorCode, commRes.ErrorMsg)
	}
	log.Infosf("Successfully report transaction[%++v] to DTS management!", root)
	return nil
}
